/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ru.ibrae.mchs.radiation.entities.controllers;

import ru.ibrae.mchs.radiation.entities.Geoobject;
import ru.ibrae.mchs.radiation.entities.controllers.exceptions.IllegalOrphanException;
import ru.ibrae.mchs.radiation.entities.controllers.exceptions.NonexistentEntityException;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import javax.persistence.EntityNotFoundException;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import ru.ibrae.mchs.radiation.entities.Comment;
import ru.ibrae.mchs.radiation.entities.Selsovet;
import ru.ibrae.mchs.radiation.entities.GSPos;
import ru.ibrae.mchs.radiation.entities.RajonOld;
import ru.ibrae.mchs.radiation.entities.Rajon;
import ru.ibrae.mchs.radiation.entities.SubjectRf;
import ru.ibrae.mchs.radiation.entities.Result;
import java.util.HashSet;
import java.util.Set;
import ru.ibrae.mchs.radiation.entities.CrossZon;
import java.util.ArrayList;

/**
 *
 * @author murr
 */
public class GeoobjectJpaController {

    public GeoobjectJpaController() {
        emf = Persistence.createEntityManagerFactory("DesktopApplication4PU");
    }
    private EntityManagerFactory emf = null;

    public EntityManager getEntityManager() {
        return emf.createEntityManager();
    }

    public void create(Geoobject geoobject) {
        if (geoobject.getResultSet() == null) {
            geoobject.setResultSet(new HashSet<Result>());
        }
        if (geoobject.getCrossZonSet() == null) {
            geoobject.setCrossZonSet(new HashSet<CrossZon>());
        }
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Comment comment = geoobject.getComment();
            if (comment != null) {
                comment = em.getReference(comment.getClass(), comment.getIdComent());
                geoobject.setComment(comment);
            }
            Selsovet selsovet = geoobject.getSelsovet();
            if (selsovet != null) {
                selsovet = em.getReference(selsovet.getClass(), selsovet.getIdSelsov());
                geoobject.setSelsovet(selsovet);
            }
            GSPos GSPos = geoobject.getGSPos();
            if (GSPos != null) {
                GSPos = em.getReference(GSPos.getClass(), GSPos.getIdPoselen());
                geoobject.setGSPos(GSPos);
            }
            RajonOld rajonOld = geoobject.getRajonOld();
            if (rajonOld != null) {
                rajonOld = em.getReference(rajonOld.getClass(), rajonOld.getIdRajonO());
                geoobject.setRajonOld(rajonOld);
            }
            Rajon rajon = geoobject.getRajon();
            if (rajon != null) {
                rajon = em.getReference(rajon.getClass(), rajon.getIdRajon());
                geoobject.setRajon(rajon);
            }
            SubjectRf subjectRf = geoobject.getSubjectRf();
            if (subjectRf != null) {
                subjectRf = em.getReference(subjectRf.getClass(), subjectRf.getId());
                geoobject.setSubjectRf(subjectRf);
            }
            Set<Result> attachedResultSet = new HashSet<Result>();
            for (Result resultSetResultToAttach : geoobject.getResultSet()) {
                resultSetResultToAttach = em.getReference(resultSetResultToAttach.getClass(), resultSetResultToAttach.getIdRezult());
                attachedResultSet.add(resultSetResultToAttach);
            }
            geoobject.setResultSet(attachedResultSet);
            Set<CrossZon> attachedCrossZonSet = new HashSet<CrossZon>();
            for (CrossZon crossZonSetCrossZonToAttach : geoobject.getCrossZonSet()) {
                crossZonSetCrossZonToAttach = em.getReference(crossZonSetCrossZonToAttach.getClass(), crossZonSetCrossZonToAttach.getCrossZonPK());
                attachedCrossZonSet.add(crossZonSetCrossZonToAttach);
            }
            geoobject.setCrossZonSet(attachedCrossZonSet);
            em.persist(geoobject);
            if (comment != null) {
                comment.getGeoobjectSet().add(geoobject);
                comment = em.merge(comment);
            }
            if (selsovet != null) {
                selsovet.getGeoobjectSet().add(geoobject);
                selsovet = em.merge(selsovet);
            }
            if (GSPos != null) {
                GSPos.getGeoobjectSet().add(geoobject);
                GSPos = em.merge(GSPos);
            }
            if (rajonOld != null) {
                rajonOld.getGeoobjectSet().add(geoobject);
                rajonOld = em.merge(rajonOld);
            }
            if (rajon != null) {
                rajon.getGeoobjectSet().add(geoobject);
                rajon = em.merge(rajon);
            }
            if (subjectRf != null) {
                subjectRf.getGeoobjectSet().add(geoobject);
                subjectRf = em.merge(subjectRf);
            }
            for (Result resultSetResult : geoobject.getResultSet()) {
                Geoobject oldGeoobjectOfResultSetResult = resultSetResult.getGeoobject();
                resultSetResult.setGeoobject(geoobject);
                resultSetResult = em.merge(resultSetResult);
                if (oldGeoobjectOfResultSetResult != null) {
                    oldGeoobjectOfResultSetResult.getResultSet().remove(resultSetResult);
                    oldGeoobjectOfResultSetResult = em.merge(oldGeoobjectOfResultSetResult);
                }
            }
            for (CrossZon crossZonSetCrossZon : geoobject.getCrossZonSet()) {
                Geoobject oldGeoobjectOfCrossZonSetCrossZon = crossZonSetCrossZon.getGeoobject();
                crossZonSetCrossZon.setGeoobject(geoobject);
                crossZonSetCrossZon = em.merge(crossZonSetCrossZon);
                if (oldGeoobjectOfCrossZonSetCrossZon != null) {
                    oldGeoobjectOfCrossZonSetCrossZon.getCrossZonSet().remove(crossZonSetCrossZon);
                    oldGeoobjectOfCrossZonSetCrossZon = em.merge(oldGeoobjectOfCrossZonSetCrossZon);
                }
            }
            em.getTransaction().commit();
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void edit(Geoobject geoobject) throws IllegalOrphanException, NonexistentEntityException, Exception {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Geoobject persistentGeoobject = em.find(Geoobject.class, geoobject.getIdNp());
            Comment commentOld = persistentGeoobject.getComment();
            Comment commentNew = geoobject.getComment();
            Selsovet selsovetOld = persistentGeoobject.getSelsovet();
            Selsovet selsovetNew = geoobject.getSelsovet();
            GSPos GSPosOld = persistentGeoobject.getGSPos();
            GSPos GSPosNew = geoobject.getGSPos();
            RajonOld rajonOldOld = persistentGeoobject.getRajonOld();
            RajonOld rajonOldNew = geoobject.getRajonOld();
            Rajon rajonOld = persistentGeoobject.getRajon();
            Rajon rajonNew = geoobject.getRajon();
            SubjectRf subjectRfOld = persistentGeoobject.getSubjectRf();
            SubjectRf subjectRfNew = geoobject.getSubjectRf();
            Set<Result> resultSetOld = persistentGeoobject.getResultSet();
            Set<Result> resultSetNew = geoobject.getResultSet();
            Set<CrossZon> crossZonSetOld = persistentGeoobject.getCrossZonSet();
            Set<CrossZon> crossZonSetNew = geoobject.getCrossZonSet();
            List<String> illegalOrphanMessages = null;
            for (CrossZon crossZonSetOldCrossZon : crossZonSetOld) {
                if (!crossZonSetNew.contains(crossZonSetOldCrossZon)) {
                    if (illegalOrphanMessages == null) {
                        illegalOrphanMessages = new ArrayList<String>();
                    }
                    illegalOrphanMessages.add("You must retain CrossZon " + crossZonSetOldCrossZon + " since its geoobject field is not nullable.");
                }
            }
            if (illegalOrphanMessages != null) {
                throw new IllegalOrphanException(illegalOrphanMessages);
            }
            if (commentNew != null) {
                commentNew = em.getReference(commentNew.getClass(), commentNew.getIdComent());
                geoobject.setComment(commentNew);
            }
            if (selsovetNew != null) {
                selsovetNew = em.getReference(selsovetNew.getClass(), selsovetNew.getIdSelsov());
                geoobject.setSelsovet(selsovetNew);
            }
            if (GSPosNew != null) {
                GSPosNew = em.getReference(GSPosNew.getClass(), GSPosNew.getIdPoselen());
                geoobject.setGSPos(GSPosNew);
            }
            if (rajonOldNew != null) {
                rajonOldNew = em.getReference(rajonOldNew.getClass(), rajonOldNew.getIdRajonO());
                geoobject.setRajonOld(rajonOldNew);
            }
            if (rajonNew != null) {
                rajonNew = em.getReference(rajonNew.getClass(), rajonNew.getIdRajon());
                geoobject.setRajon(rajonNew);
            }
            if (subjectRfNew != null) {
                subjectRfNew = em.getReference(subjectRfNew.getClass(), subjectRfNew.getId());
                geoobject.setSubjectRf(subjectRfNew);
            }
            Set<Result> attachedResultSetNew = new HashSet<Result>();
            for (Result resultSetNewResultToAttach : resultSetNew) {
                resultSetNewResultToAttach = em.getReference(resultSetNewResultToAttach.getClass(), resultSetNewResultToAttach.getIdRezult());
                attachedResultSetNew.add(resultSetNewResultToAttach);
            }
            resultSetNew = attachedResultSetNew;
            geoobject.setResultSet(resultSetNew);
            Set<CrossZon> attachedCrossZonSetNew = new HashSet<CrossZon>();
            for (CrossZon crossZonSetNewCrossZonToAttach : crossZonSetNew) {
                crossZonSetNewCrossZonToAttach = em.getReference(crossZonSetNewCrossZonToAttach.getClass(), crossZonSetNewCrossZonToAttach.getCrossZonPK());
                attachedCrossZonSetNew.add(crossZonSetNewCrossZonToAttach);
            }
            crossZonSetNew = attachedCrossZonSetNew;
            geoobject.setCrossZonSet(crossZonSetNew);
            geoobject = em.merge(geoobject);
            if (commentOld != null && !commentOld.equals(commentNew)) {
                commentOld.getGeoobjectSet().remove(geoobject);
                commentOld = em.merge(commentOld);
            }
            if (commentNew != null && !commentNew.equals(commentOld)) {
                commentNew.getGeoobjectSet().add(geoobject);
                commentNew = em.merge(commentNew);
            }
            if (selsovetOld != null && !selsovetOld.equals(selsovetNew)) {
                selsovetOld.getGeoobjectSet().remove(geoobject);
                selsovetOld = em.merge(selsovetOld);
            }
            if (selsovetNew != null && !selsovetNew.equals(selsovetOld)) {
                selsovetNew.getGeoobjectSet().add(geoobject);
                selsovetNew = em.merge(selsovetNew);
            }
            if (GSPosOld != null && !GSPosOld.equals(GSPosNew)) {
                GSPosOld.getGeoobjectSet().remove(geoobject);
                GSPosOld = em.merge(GSPosOld);
            }
            if (GSPosNew != null && !GSPosNew.equals(GSPosOld)) {
                GSPosNew.getGeoobjectSet().add(geoobject);
                GSPosNew = em.merge(GSPosNew);
            }
            if (rajonOldOld != null && !rajonOldOld.equals(rajonOldNew)) {
                rajonOldOld.getGeoobjectSet().remove(geoobject);
                rajonOldOld = em.merge(rajonOldOld);
            }
            if (rajonOldNew != null && !rajonOldNew.equals(rajonOldOld)) {
                rajonOldNew.getGeoobjectSet().add(geoobject);
                rajonOldNew = em.merge(rajonOldNew);
            }
            if (rajonOld != null && !rajonOld.equals(rajonNew)) {
                rajonOld.getGeoobjectSet().remove(geoobject);
                rajonOld = em.merge(rajonOld);
            }
            if (rajonNew != null && !rajonNew.equals(rajonOld)) {
                rajonNew.getGeoobjectSet().add(geoobject);
                rajonNew = em.merge(rajonNew);
            }
            if (subjectRfOld != null && !subjectRfOld.equals(subjectRfNew)) {
                subjectRfOld.getGeoobjectSet().remove(geoobject);
                subjectRfOld = em.merge(subjectRfOld);
            }
            if (subjectRfNew != null && !subjectRfNew.equals(subjectRfOld)) {
                subjectRfNew.getGeoobjectSet().add(geoobject);
                subjectRfNew = em.merge(subjectRfNew);
            }
            for (Result resultSetOldResult : resultSetOld) {
                if (!resultSetNew.contains(resultSetOldResult)) {
                    resultSetOldResult.setGeoobject(null);
                    resultSetOldResult = em.merge(resultSetOldResult);
                }
            }
            for (Result resultSetNewResult : resultSetNew) {
                if (!resultSetOld.contains(resultSetNewResult)) {
                    Geoobject oldGeoobjectOfResultSetNewResult = resultSetNewResult.getGeoobject();
                    resultSetNewResult.setGeoobject(geoobject);
                    resultSetNewResult = em.merge(resultSetNewResult);
                    if (oldGeoobjectOfResultSetNewResult != null && !oldGeoobjectOfResultSetNewResult.equals(geoobject)) {
                        oldGeoobjectOfResultSetNewResult.getResultSet().remove(resultSetNewResult);
                        oldGeoobjectOfResultSetNewResult = em.merge(oldGeoobjectOfResultSetNewResult);
                    }
                }
            }
            for (CrossZon crossZonSetNewCrossZon : crossZonSetNew) {
                if (!crossZonSetOld.contains(crossZonSetNewCrossZon)) {
                    Geoobject oldGeoobjectOfCrossZonSetNewCrossZon = crossZonSetNewCrossZon.getGeoobject();
                    crossZonSetNewCrossZon.setGeoobject(geoobject);
                    crossZonSetNewCrossZon = em.merge(crossZonSetNewCrossZon);
                    if (oldGeoobjectOfCrossZonSetNewCrossZon != null && !oldGeoobjectOfCrossZonSetNewCrossZon.equals(geoobject)) {
                        oldGeoobjectOfCrossZonSetNewCrossZon.getCrossZonSet().remove(crossZonSetNewCrossZon);
                        oldGeoobjectOfCrossZonSetNewCrossZon = em.merge(oldGeoobjectOfCrossZonSetNewCrossZon);
                    }
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            String msg = ex.getLocalizedMessage();
            if (msg == null || msg.length() == 0) {
                Integer id = geoobject.getIdNp();
                if (findGeoobject(id) == null) {
                    throw new NonexistentEntityException("The geoobject with id " + id + " no longer exists.");
                }
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void destroy(Integer id) throws IllegalOrphanException, NonexistentEntityException {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Geoobject geoobject;
            try {
                geoobject = em.getReference(Geoobject.class, id);
                geoobject.getIdNp();
            } catch (EntityNotFoundException enfe) {
                throw new NonexistentEntityException("The geoobject with id " + id + " no longer exists.", enfe);
            }
            List<String> illegalOrphanMessages = null;
            Set<CrossZon> crossZonSetOrphanCheck = geoobject.getCrossZonSet();
            for (CrossZon crossZonSetOrphanCheckCrossZon : crossZonSetOrphanCheck) {
                if (illegalOrphanMessages == null) {
                    illegalOrphanMessages = new ArrayList<String>();
                }
                illegalOrphanMessages.add("This Geoobject (" + geoobject + ") cannot be destroyed since the CrossZon " + crossZonSetOrphanCheckCrossZon + " in its crossZonSet field has a non-nullable geoobject field.");
            }
            if (illegalOrphanMessages != null) {
                throw new IllegalOrphanException(illegalOrphanMessages);
            }
            Comment comment = geoobject.getComment();
            if (comment != null) {
                comment.getGeoobjectSet().remove(geoobject);
                comment = em.merge(comment);
            }
            Selsovet selsovet = geoobject.getSelsovet();
            if (selsovet != null) {
                selsovet.getGeoobjectSet().remove(geoobject);
                selsovet = em.merge(selsovet);
            }
            GSPos GSPos = geoobject.getGSPos();
            if (GSPos != null) {
                GSPos.getGeoobjectSet().remove(geoobject);
                GSPos = em.merge(GSPos);
            }
            RajonOld rajonOld = geoobject.getRajonOld();
            if (rajonOld != null) {
                rajonOld.getGeoobjectSet().remove(geoobject);
                rajonOld = em.merge(rajonOld);
            }
            Rajon rajon = geoobject.getRajon();
            if (rajon != null) {
                rajon.getGeoobjectSet().remove(geoobject);
                rajon = em.merge(rajon);
            }
            SubjectRf subjectRf = geoobject.getSubjectRf();
            if (subjectRf != null) {
                subjectRf.getGeoobjectSet().remove(geoobject);
                subjectRf = em.merge(subjectRf);
            }
            Set<Result> resultSet = geoobject.getResultSet();
            for (Result resultSetResult : resultSet) {
                resultSetResult.setGeoobject(null);
                resultSetResult = em.merge(resultSetResult);
            }
            em.remove(geoobject);
            em.getTransaction().commit();
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public List<Geoobject> findGeoobjectEntities() {
        return findGeoobjectEntities(true, -1, -1);
    }

    public List<Geoobject> findGeoobjectEntities(int maxResults, int firstResult) {
        return findGeoobjectEntities(false, maxResults, firstResult);
    }

    private List<Geoobject> findGeoobjectEntities(boolean all, int maxResults, int firstResult) {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            cq.select(cq.from(Geoobject.class));
            Query q = em.createQuery(cq);
            if (!all) {
                q.setMaxResults(maxResults);
                q.setFirstResult(firstResult);
            }
            return q.getResultList();
        } finally {
            em.close();
        }
    }

    public Geoobject findGeoobject(Integer id) {
        EntityManager em = getEntityManager();
        try {
            return em.find(Geoobject.class, id);
        } finally {
            em.close();
        }
    }

    public int getGeoobjectCount() {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            Root<Geoobject> rt = cq.from(Geoobject.class);
            cq.select(em.getCriteriaBuilder().count(rt));
            Query q = em.createQuery(cq);
            return ((Long) q.getSingleResult()).intValue();
        } finally {
            em.close();
        }
    }
}
